import { Dep } from "./Dep.js";
import Vue from "./Vue.js";
import { Watcher } from "./Watcher.js";
export function observer(vm: Vue, data: Record<string, any>) {

    const dep = new Dep()


    Object.keys(data).forEach((key) => {
        let internalValue = data[key]
        Object.defineProperty(vm, key, {
            get(): any {
                if (Dep.target) {
                    dep.pushDep(Dep.target)
                }

                return internalValue
            },
            set(newValue: any): void {
                if (newValue === internalValue) {
                    return
                }
                internalValue = newValue
                dep.notify()
            }
        })
    })

}


export function complie(vm: Vue) {
    // 使用querySelector获取vm实例中$el对应的DOM元素
    const el: HTMLElement|null = document.querySelector(vm.$el);
    // 如果没有获取到元素，则抛出错误
    if (!el) {
        throw new Error('没有找到要绑定的元素');
    }
    // 定义正则表达式，用于匹配插值表达式
    const reg = /\{\{(.*)\}\}/;

    // 创建一个文档片段，用于后续操作DOM时减少页面重绘
    const fg = document.createDocumentFragment();

 

    // 遍历el的所有子节点
    while (el.firstChild) {
        // 将当前子节点强制转换为HTMLElement类型
        const child = el.firstChild as HTMLElement;

        // 如果子节点是元素节点
        if (child.nodeType === Node.ELEMENT_NODE) {
            // 如果子节点的innerText匹配插值表达式
            if (reg.test(child.innerText || '')) {
                // 获取匹配到的第一个捕获组，并去除首尾空格
                const vmKey = RegExp.$1.trim();
                // 创建Watcher实例，用于依赖收集和更新视图
                new Watcher(vm, child, vmKey);
            } else {
                // 遍历子节点的所有属性
                Array.from(child.attributes).forEach((attr) => {
                    // 获取属性名
                    const attrName = attr.name;
                    // 如果属性名为v-model
                    if (attrName === 'v-model') {
                        // 获取匹配到的第一个捕获组，并去除首尾空格
                        const vmKey = RegExp.$1.trim();
                        // 为元素添加input事件监听
                        child.addEventListener('input', (ev: Event) => {
                            // 获取事件的目标元素，并断言为HTMLInputElement类型
                            const target = ev.target as HTMLInputElement;
                            // 将目标元素的value值赋给vm实例对应的属性
                            vm[vmKey] = target.value;
                        });
                    }
                });
            }
        } else if (child.nodeType === Node.TEXT_NODE && reg.test(child.nodeValue || '')) {
            // 如果子节点是文本节点，并且nodeValue匹配插值表达式
            const vmKey = RegExp.$1.trim();
            // 创建Watcher实例，用于依赖收集和更新视图
            new Watcher(vm, child, vmKey);
        }
        // 将处理过的子节点追加到文档片段中
        fg.appendChild(child);
    }

    // 将文档片段追加回el元素中，完成DOM的更新
    el.appendChild(fg);
}